/**************************************************************************************************
 
  Phyplus Microelectronics Limited confidential and proprietary. 
  All rights reserved.

  IMPORTANT: All rights of this software belong to Phyplus Microelectronics 
  Limited ("Phyplus"). Your use of this Software is limited to those 
  specific rights granted under  the terms of the business contract, the 
  confidential agreement, the non-disclosure agreement and any other forms 
  of agreements as a customer or a partner of Phyplus. You may not use this 
  Software unless you agree to abide by the terms of these agreements. 
  You acknowledge that the Software may not be modified, copied, 
  distributed or disclosed unless embedded on a Phyplus Bluetooth Low Energy 
  (BLE) integrated circuit, either as a product or is integrated into your 
  products.  Other than for the aforementioned purposes, you may not use, 
  reproduce, copy, prepare derivative works of, modify, distribute, perform, 
  display or sell this Software and/or its documentation for any purposes.

  YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
  PROVIDED AS IS WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
  INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
  NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
  PHYPLUS OR ITS SUBSIDIARIES BE LIABLE OR OBLIGATED UNDER CONTRACT,
  NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
  LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
  INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
  OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
  OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
  (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
  
**************************************************************************************************/

/*******************************************************************************
* @file		i2c_comman.h
* @brief	i2c General Configuration
* @version	1.0
* Copyright(C) 2016, PhyPlus Semiconductor
* All rights reserved.
*******************************************************************************/

#ifndef __I2C_COMMON_H__
#define __I2C_COMMON_H__

/*******************************************************************************
*@ Module    	  	: Includes
*@ Description    :  NULL
*******************************************************************************/
#include "ap_cp.h"
#include "gpio.h"
#include "hal_mcu.h"

/*******************************************************************************
*@ Module    	  	:  pre-compile
*@ Description    :  NULL
*******************************************************************************/


/*******************************************************************************
*@ Module    			:  Macro Define
*@ Description    :  IIC Error Code
*******************************************************************************/
#define PPlus_IIC_SUCCESS							0
#define PPlus_ERR_IIC_ADDRESS 				0xFE
#define PPlus_ERR_IIC_ID							0xFD
#define PPLUS_ERR_IIC_BUSY						0xFC
#define PPLUS_ERR_IIC_ENABLE					0xFB
#define PPlus_ERR_IIC_FAILURE					0xFF
	
/*******************************************************************************
*@ Module    			:  Macro Define
*@ Description    :  IIC InValid Handle
*******************************************************************************/
#define PPlus_INVALID_HANDLE					0xFF

/*******************************************************************************
*@ Module    			:  Macro Define
*@ Description    :  The number of IIC Module(Two IIC:IIC0,IIC1)
*******************************************************************************/
#define IIC_COUNT	2

/*******************************************************************************
*@ Module    			:  Macro Define
*@ Description    :  Indicate IIC Module
*******************************************************************************/
#define IIC_Module0			0
#define IIC_Module1			1

/*******************************************************************************
*@ Module    			:  Macro Define
*@ Description    :  IIC Bus Read or Wirte Device
*******************************************************************************/
#define I2C_COMMAND_READ		0x01
#define I2C_COMMAND_WRITE		0x00

/*******************************************************************************
*@ Module    			:  Macro Define
*@ Description    :  IIC Bus Read or Write data from FIFO
*******************************************************************************/
#define I2C_Data_READ				0x01
#define I2C_Data_WRITE			0x00

/*******************************************************************************
*@ Module    			:  Macro Define
*@ Description    :  Can not be used IIC Slave Address Length
*******************************************************************************/
#define I2C_NOT_USED_SLAVE_ADDRLEN	4

/*******************************************************************************
*@ Module    			:  Macro Define
*@ Description    :  None
*******************************************************************************/
#define I2C_IC_DEFAULT_TAR_UPDATE			0
#define I2C_IC_CLK_TYPE								1

/*******************************************************************************
*@ Module    			:  Macro Define
*@ Description    :  IIC Default Master/Slave Address
*******************************************************************************/
#define I2C_IC_DEFAULT_ADDR 0x0010

/*******************************************************************************
*@ Module    	  	:  I2C Buffer Length
*@ Description    :  relate to RX FIFO & TX FIFO
*******************************************************************************/
#define I2C_FIFO_DEPTH 			8
#define I2C_RX_TL_CNT				I2C_FIFO_DEPTH
#define I2C_TX_TL_CNT				I2C_FIFO_DEPTH	

/*******************************************************************************
*@ Module    			:  Macro Define
*@ Description    :  IC_CON Bit Field Description
*******************************************************************************/
// Determine IIC Slave enable or disable after reset(salve is enable in reset state)
// if slave enabled , MASTER_MODE should be disabled
#define IC_CON_IC_SLAVE_DISABLE		0x0040

// Determine whether restart conditions may be send when act as a master
// when act an a master , must enable this function
#define IC_CON_IC_RESTART_EN		0x0020

#define IC_CON_IC_10BITADDR_MASTER	0x0010
// Determine the IIC Master Address Mode(10bit)

// Determine the IIC Slave Address Mode(10bit)
#define IC_CON_IC_10BITADDR_SLAVE	0x0008

// Determine IIC Speed Mode 
#define IC_CON_IC_SPEED_100K		0x0002
#define IC_CON_IC_SPEED_400K		0x0004
#define IC_CON_IC_SPEED_3_4M		0x0006

// Determine IIC Master Enable
#define IC_CON_MASTER_MODE			0x0001

/*******************************************************************************
*@ Module    			:  Macro Define
*@ Description    :  IC_TAR Bit Field Description
*******************************************************************************/
// this bit related to I2C_IC_DEFAULT_TAR_UPDATE Value
#define IC_TAR_IC_10BITADDR_MASTER	0x1000

// Indicate whether performance a Gengral call or start byte Command
// relate to IC_TAR_GC_OR_START
#define IC_TAR_SPECIAL_COMMAND_ENABLE	0x0800

// Dependency IC_TAR_SPECIAL_COMMAND_ENABLE 
// if set, Start Byte,otherwise General Call
// General Call:only writes may be performed.when read resault TX_ABRT
// Start Byte:send Start Byte(0x01) to Synchronizate IIC Clock
#define IC_TAR_GC_OR_START				0x0400

// IC Default Slave Address
#define IC_TAR_DEFAULT_SLAVE_ADDRESS	I2C_IC_DEFAULT_TAR_SLAVE_ADDR

/*******************************************************************************
*@ Module    			:  Macro Define
*@ Description    :  IC_SAR
*******************************************************************************/
#define IC_SAR_DEFAUT_SLAVE_ADDRESS		I2C_IC_DEFAULT_TAR_SLAVE_ADDR

/*******************************************************************************
*@ Module    	  	:  I2C Interrupt Status Register
*@ Description    :  Interrupt Status bit(cleared by reading the matching interrupt clear register.)
*******************************************************************************/
#define	I2C_INTR_STAT_RX_UNDER			0x0001
#define	I2C_INTR_STAT_RX_OVER			0x0002
#define I2C_INTR_STAT_RX_FULL			0x0004
#define I2C_INTR_STAT_TX_OVER			0x0008
#define I2C_INTR_STAT_TX_EMPTY			0x0010
#define I2C_INTR_STAT_RD_REQ				0x0020
#define I2C_INTR_STAT_TX_ABRT			0x0040
#define I2C_INTR_STAT_RX_DONE			0x0080
#define I2C_INTR_STAT_ACTIVITY			0x0100
#define I2C_INTR_STAT_STOP_DET			0x0200
#define I2C_INTR_STAT_START_DET			0x0400
#define	I2C_INTR_STAT_GEN_CALL			0x0800

/*******************************************************************************
*@ Module    	  	:  I2C Interrupt Mask Register
*@ Description    :  Interrupt MASK bit
*******************************************************************************/
#define	I2C_MASK_RX_UNDER			0x0001
#define	I2C_MASK_RX_OVER			0x0002
#define I2C_MASK_RX_FULL			0x0004
#define I2C_MASK_TX_OVER			0x0008
#define I2C_MASK_TX_EMPTY			0x0010
#define I2C_MASK_RD_REQ				0x0020
#define I2C_MASK_TX_ABRT			0x0040
#define I2C_MASK_RX_DONE			0x0080
#define I2C_MASK_ACTIVITY			0x0100
#define I2C_MASK_STOP_DET			0x0200
#define I2C_MASK_START_DET		0x0400
#define	I2C_MASK_GEN_CALL			0x0800
#define I2C_DISABLE_ALL_INTR	0

/*******************************************************************************
*@ Module    	  	:  I2C Raw Interrupt Register
*@ Description    :  Interrupt MASK bit
*******************************************************************************/
#define	I2C_RAW_INTR_RX_UNDER			0x0001
#define	I2C_RAW_INTR_RX_OVER			0x0002
#define I2C_RAW_INTR_RX_FULL			0x0004
#define I2C_RAW_INTR_TX_OVER			0x0008
#define I2C_RAW_INTR_TX_EMPTY			0x0010
#define I2C_RAW_INTR_RD_REQ				0x0020
#define I2C_RAW_INTR_TX_ABRT			0x0040
#define I2C_RAW_INTR_RX_DONE			0x0080
#define I2C_RAW_INTR_ACTIVITY			0x0100
#define I2C_RAW_INTR_STOP_DET			0x0200
#define I2C_RAW_INTR_START_DET		0x0400
#define	I2C_RAW_INTR_GEN_CALL			0x0800

/*******************************************************************************
*@ Module    	  	:  I2C ENABLE Status Register
*@ Description    :  I2C ENABLE STATUS Bit
*******************************************************************************/
#define I2C_ENSTA_IC_ENABLE_STATUS		0x0001
#define I2C_ENSTA_SLV_RX_ABORT			0x0002
#define I2C_ENSTA_SLV_RX_DATA_LOST		0x0004

/*******************************************************************************
*@ Module    	  	:  I2C Status Register
*@ Description    :  Only read register ,indicate current transfer stauts and FIFO status
*******************************************************************************/
#define I2C_STAT_SLV_ACTIVITY			0x0040
#define I2C_STAT_MST_ACTIVITY			0x0020
//Receive FIFO Completely Full
#define I2C_STAT_RFF					0x0010
//Receive FIFO Not Empty
#define I2C_STAT_RFNF					0x0008
// Transmit FIFO Completely Empty
#define I2C_STAT_TFE					0x0004
// Transmit FIFO Not Full
#define I2C_STAT_TFNF					0x0002
#define I2C_STAT_ACTIVITY				0x0001

/*******************************************************************************
*@ Module    	  	:  I2C Transmit Abort Source Register
*@ Description    :   indicate the source of the TX_ABRT 
*******************************************************************************/
#define I2C_ABRT_7B_ADDR_NOACK			0x0001
#define I2C_ABRT_10B_ADDR1_NOACK		0x0002
#define I2C_ABRT_10B_ADDR2_NOACK		0x0004
#define I2C_ABRT_TXDATA_NOACK			0x0008
// master send a General Call , but no slave ACK
#define I2C_ABRT_GCALL_NOACK			0x0010
// master send data to the bus , but user programmed the data direction is read
// from the bus(relate to IC_DATA_CMD[8])
#define	I2C_ABRT_GCALL_READ				0x0020
// master in high speed mode ,and its code was ACK(Should not ACK)
#define I2C_ABRT_HS_ACKDET				0x0040
// master send START Byte and detect ACK(Should not ACK)
#define I2C_ABRT_SBYTE_ACKDET			0x0080
// the restart is diabled,and the user is trying to use the master to transmit
// data in high speed mode
#define I2C_ABRT_HS_NORTART				0x0100

//
#define I2C_ABRT_SBYTE_NORESTART		0x0200

#define I2C_ABRT_10B_RD_NORSTART		0x0400
// user tries to initiate a master operation with the master mode disabled
#define	I2C_ABRT_MASTER_DIS				0x0800

#define I2C_ABR_LOST					0x1000

// slave receive a read command ,but there's some data exists in TX FIFO, 
// and issues interrupt to flush old TX FIFO
#define I2C_ABRT_SLVFLUSH_TXFIFO		0x2000

#define I2C_ABRT_SLV_ABRLOST			0x4000

// slave transmit data to the master , and use the read data command from the 
// bus(relate to IC_DATA_CMD[8])
#define I2C_ABRT_SLVRD_INTX				0x8000

/*******************************************************************************
*@ Module    			:  IIC Work Mode
*@ Description    :  None
*******************************************************************************/
typedef enum{
	Slave = 0,
	Master = IC_CON_IC_SLAVE_DISABLE | IC_CON_IC_RESTART_EN | IC_CON_MASTER_MODE,
}I2C_WorkMode;

/*******************************************************************************
*@ Module    			:  IIC Speed Mode
*@ Description    :  None
*******************************************************************************/
typedef enum{
	 SPEED_STANDARD = 0x0002,        		//standard mode
	 SPEED_FAST = 0x0004,                	//fast mode
	 SPEED_HIGH = 0x0006,	               	//high mode
}I2C_SPEED_e;

/*******************************************************************************
*@ Module    			:  IIC Clock
*@ Description    :  None
*******************************************************************************/
typedef enum
{
    I2C_CLOCK_100K  = 0x0002,
    I2C_CLOCK_400K	= 0x0004,
    I2C_CLOCK_3_4M 	= 0x0006,
} I2C_CLOCK_e;

/*******************************************************************************
*@ Module    			:  IIC Address Mode
*@ Description    :  Only support 7 bit Address,be careful while using
*******************************************************************************/
typedef enum
{
	I2C_ADDR_7bit = 0,
	I2C_ADDR_10bit
}I2C_ADDRESS_e;

/*******************************************************************************
*@ Module    			:  transfer mode
*@ Description    :   
*  					I2C_MODE_BLOCKING blocks task execution while an I2C transfer is in progress
*  					I2C_MODE_CALLBACK does not block task execution; but calls a callback
*  					function when the I2C transfer has completed
*******************************************************************************/
typedef enum
{
    I2C_MODE_BLOCKING,  /*!< I2C_transfer blocks execution*/
    I2C_MODE_CALLBACK   /*!< I2C_transfer queues transactions and does not block */
} I2C_TransferMode;

/*******************************************************************************
*@ Module    			: 	I2C Event enum
*@ Description    :   None
*******************************************************************************/
typedef enum{
	// INTR SOURCE EVENT
	I2C_RX_UNDER_Evt = 0x0001,		
	I2C_RX_OVER_Evt = 0x0002,
	I2C_RX_FULL_Evt = 0x0004,	
	I2C_TX_OVER_Evt = 0x0008,
	I2C_TX_EMPTY_Evt = 0x0010,
	I2C_RD_REQ_Evt = 0x0020,
	I2C_TX_ABRT_Evt = 0x0040,
	I2C_RX_DONE_Evt = 0x0080,
	I2C_ACTIVITY_Evt = 0x0100,
	I2C_STOP_DET_Evt = 0x0200,
	I2C_START_DET_Evt = 0x0400,
	I2C_GEN_CALL_Evt = 0x0800,
	// User Event
	I2C_DINIT_SUCCESS = 0x1000
}I2C_EVT;

/*******************************************************************************
*@ Module    			: 	I2C Event 
*@ Description    :   None
*******************************************************************************/
typedef struct {
  I2C_EVT  type;
  uint8_t   len;
}I2C_Evt_t;

/*******************************************************************************
*@ Module    			: 	Function *p
*@ Description    :   None
*******************************************************************************/
typedef void (*I2C_Hdl_t)(I2C_Evt_t *pev);
	


/*******************************************************************************
*@ Module    			: 	I2C Master Paramter structure
*@ Description    :   None
*******************************************************************************/
typedef struct
{
	// General
	uint8_t						id;											// set
	I2C_WorkMode			workmode;								// init some Para ,according to workmode
	I2C_CLOCK_e				ClockMode;
	I2C_ADDRESS_e 		AddressMode;
	bool       				use_fifo;								// check if use fifo,default used
	uint8_t						RX_FIFO_Len;						// RX , TX FIFO SET
	uint8_t						Tx_FIFO_Len;
	GPIO_Pin_e 				SDA_PIN;								// I2C Pin 
	GPIO_Pin_e 				SCL_PIN;
	I2C_TransferMode 	TransferMode;						// according to TransferMode, that evt_handler can be 
																						// enable or disable
	I2C_Hdl_t 				evt_handler;
	
	uint8_t						Master_Addressing;			// TAR,when as master
	uint32_t					IC_xS_SCL_HCNT;
	uint32_t					IC_xS_SCL_LCNT;
	
}I2C_Master_Parameter;

/*******************************************************************************
*@ Module    	  	:  Master Default Init Parameter
*@ Description    :   None 
*******************************************************************************/
//I2CCOM_Ext I2C_Parameter I2C_DefaultPara;

/*******************************************************************************
*@ Module    			:  Function statement
*@ Description    :  
*******************************************************************************/
uint8_t Hal_Check_IIC_IsAlready_Closed(void);

/*******************************************************************************
*@ Module    			:  Get_IIC_Instance
*@ Description    :  
					[para in]:id,iic module id 0 or 1
					[return]:instance address
*******************************************************************************/
AP_I2C_TypeDef *Hal_Get_IIC_Instance(uint8_t id);

/*******************************************************************************
*@ Module    			:  Hal_GetIIC_ModuleID
*@ Description    :  None
*******************************************************************************/
MODULE_e Hal_GetIIC_ModuleID(uint8_t id);

/*******************************************************************************
*@ Module    			:  Hal_GetIIC_Interrupt ID
*@ Description    :  None
*******************************************************************************/
uint8_t Hal_GetIIC_IRQID(uint8_t id);

/*******************************************************************************
*@ Module    			:  Hal_GetIIC_PIN_Fmux ID
*@ Description    :  None
*******************************************************************************/
void Hal_GetIIC_PIN_Fmux(uint8_t id,Fmux_Type_e *SCL_Fmux,Fmux_Type_e *SDA_Fmux);

/*******************************************************************************
*@ Module    			:  IIC Register CallBack Function
*@ Description    :  
					[para in]:id,iic module 0,1;cb , call back function
*******************************************************************************/
uint8_t Hal_IIC_Register_CallBack(uint8_t id,I2C_Hdl_t cb);

/*******************************************************************************
*@ Module    			:  IIC unRegister CallBack Function
*@ Description    :  [para in]:id,iic module 0,1
*******************************************************************************/
uint8_t Hal_IIC_unRegister_CallBack(uint8_t id);

/*******************************************************************************
*@ Module    			:  IIC Check IIC Valid
*@ Description    :  [para in]:id,iic module 0,1
*******************************************************************************/
uint8_t Hal_IIC_Valid_Check(uint8_t id);

/*******************************************************************************
*@ Module    			:  IIC Check IIC Address Valid
*@ Description    :  [para in]:Addr,usr set master or slave address
*******************************************************************************/
uint8_t Hal_IIC_Addr_Valid(uint8_t Addr);

/*******************************************************************************
*@ Module    			:  Check IIC Closed Success
*@ Description    :  [para in]:Ins,the instance wanted to check
*******************************************************************************/
uint8_t Hal_Check_IIC_Closed(AP_I2C_TypeDef *Ins);

/*******************************************************************************
*@ Module    			:  IIC Receive data from RX FIFO
*@ Description    :  [para in]:Ins,the instance wanted to READ Data
*******************************************************************************/
uint8_t Hal_IIC_Read_RXFIFO(AP_I2C_TypeDef *Ins);

/*******************************************************************************
*@ Module    			:  Hal_INTR_SOURCE_Clear
*@ Description    :  [para in]:Ins,the instance wanted to READ Data,irqs:interrupt source
*******************************************************************************/
void Hal_INTR_SOURCE_Clear(AP_I2C_TypeDef *Ins,uint32_t irqs);

/*******************************************************************************
*@ Module    			:  Hal_IIC_Write_TXFIFO
*@ Description    :  [para in]:Ins,the instance wanted to write,
*******************************************************************************/
void Hal_IIC_Write_TXFIFO(AP_I2C_TypeDef *Ins,uint8_t data);



void Hal_TRANS_ABRT_SourceCheck(void);

void __attribute__((weak)) Hal_I2C0_IRQHandler(void);
void __attribute__((weak)) Hal_I2C1_IRQHandler(void);

#endif
